package com.detrum.detrumdata.service;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.MediaMuxer;
import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;


import com.detrum.DeviceUpdateReceiver;
import com.detrum.base.BaseFinal;
import com.detrum.base.BaseStatic;
import com.detrum.base.ServiceStatic;
import com.detrum.bean.CodecBean;
import com.detrum.bean.FileBean;
import com.detrum.bean.VersionBean;
import com.detrum.bean.ViewPagerItem;
import com.detrum.detrumdata.R;
import com.detrum.detrumdata.jlibrtp.FrameNode;
import com.detrum.detrumdata.jlibrtp.PktBuffer;
import com.detrum.detrumdata.jlibrtp.RtpPkt;
import com.detrum.detrumdata.newd.DFrame;
import com.detrum.detrumdata.newd.DFrameType;
import com.detrum.detrumdata.newd.DProtocol;
import com.detrum.sqlite.SqliteDeviceOperate;
import com.detrum.sqlite.SqliteMediaOperation;
import com.detrum.sqlite.SqliteVersionOperate;
import com.detrum.utils.MyMethod;

import org.jcodec.api.transcode.Transcoder;
import org.jcodec.codecs.h264.BufferH264ES;
import org.jcodec.codecs.h264.H264Decoder;
import org.jcodec.codecs.h264.io.model.NALUnit;
import org.jcodec.codecs.h264.io.model.NALUnitType;
import org.jcodec.codecs.h264.io.model.SliceHeader;
import org.jcodec.common.Codec;
import org.jcodec.common.Muxer;
import org.jcodec.common.MuxerTrack;
import org.jcodec.common.io.NIOUtils;
import org.jcodec.common.io.SeekableByteChannel;
import org.jcodec.common.model.Packet;
import org.jcodec.common.model.TapeTimecode;
import org.jcodec.containers.mp4.MP4Packet;
import org.jcodec.containers.mp4.muxer.MP4Muxer;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.detrum.base.BaseStatic.savaInfoToSD;


public class USBConnetService extends Service {
    private final String TAG = "USBConnetService";
    private SendUsbDataRunnable usbDataRunnable;
    private ExecutorService threadExecutor;
    private CodecData codecData;
    private ParcelFileDescriptor mFileDescriptor = null;
    private FileInputStream mInputStream = null;
    private FileOutputStream mOutputStream = null;
    private UsbAccessory mAccessory = null;
    private PktBuffer pktBuffer = new PktBuffer();
    private DProtocol dprotocl = new DProtocol(this);
    private FileDescriptor fd;
    private UsbManager mUSBManager;
    private final String ACTION_USB_PERMISSION =
            "com.android.example.USB_PERMISSION";

    private Vector<CodecBean> vector;
    private Thread setDataThread;
    //定时器
    private long time;
    private Timer timer;
    private MyTask myTask;
    private final UsbReceiver mUsbReceiver = new UsbReceiver();
    private UsbServiceCall1 usbServiceCall1;
    private UsbServiceCall2 usbServiceCall2;
    private Handler handler = new Handler();

    private DeviceUpdateReceiver deviceUpdateReceiver;
    private boolean isenable;

    public void setUsbServiceCall1(UsbServiceCall1 usbServiceCall1) {
        this.usbServiceCall1 = usbServiceCall1;
    }

    public void setUsbServiceCall2(UsbServiceCall2 usbServiceCall2) {
        this.usbServiceCall2 = usbServiceCall2;
    }

    /**
     * 超时线程
     */
    class MyTask extends TimerTask {

        @Override
        public void run() {
            long current_time = System.currentTimeMillis();
            if (current_time >= (time + 5000)) {
                savaInfoToSD("mInputStream read Timeout 5秒内没有接受到任何数据");
                ServiceStatic.isAcceptData = false;
                ServiceStatic.isAccessoryConnect = false;
                if (usbServiceCall1 != null) {
                    usbServiceCall1.disconnect();//通知附件获取失败
                }
            }
        }
    }

    public class UsbReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case UsbManager.ACTION_USB_ACCESSORY_ATTACHED:
                    savaInfoToSD("ACTION_USB_ACCESSORY_ATTACHED");
                    break;
                case UsbManager.ACTION_USB_ACCESSORY_DETACHED:
                    savaInfoToSD("ACTION_USB_ACCESSORY_DETACHED");
                    if (!ServiceStatic.isAccessoryConnect) {
                        return;
                    }
                    ServiceStatic.isAccessoryConnect = false;
                    UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                    if (accessory != null) {
                        closeAccessory();
                    }
                    if (usbServiceCall1 != null) {
                        usbServiceCall1.disconnect();//通知附件获取失败
                    }
                    USBConnetService.this.stopSelf();
                    break;
                case ACTION_USB_PERMISSION:
                    synchronized (this) {
                        mAccessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                            if (mAccessory != null) {
                                openAccessory(mAccessory);
                            }
                        } else {
                            savaInfoToSD("permission is fail");
                        }
                    }
                    break;
            }
        }
    }

    //发送指令
    class SendUsbDataRunnable implements Runnable {
        public byte[] usbData;
        public int usbDataLength;
        public int doffset;

        public SendUsbDataRunnable() {
        }

        public SendUsbDataRunnable(byte[] usbData, int usbDataLength, int doffset) {
            this.usbData = usbData;
            this.usbDataLength = usbDataLength;
            this.doffset = doffset;
        }

        @Override
        public void run() {
            if (mOutputStream == null) return;
            try {
                if (usbDataLength == 0) return;
                if (doffset + usbDataLength > usbData.length) {
                    return;
                }

                byte[] usbSendData = new byte[usbDataLength];
                for (int i = doffset; i < usbDataLength; i++) {
                    usbSendData[i] = usbData[i];
                }
                if (usbSendData == null) {
                    return;
                }
                mOutputStream.write(usbSendData, 0, usbDataLength);
                mOutputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                usbDataRunnable.usbData = null;
                usbDataLength = 0;
                doffset = 0;
            }
        }
    }

    public USBConnetService() {
    }

    private NotificationCompat.Builder builder;
    private NotificationManager manager;

    @Override
    public void onCreate() {
        super.onCreate();
        vector = new Vector<>();
        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
        filter.addAction(ACTION_USB_PERMISSION);
        registerReceiver(mUsbReceiver, filter);
        ServiceStatic.isLaunchUsbService = true;
        timer = new Timer();
        savaInfoToSD("UsbService register broadcast");
        mUSBManager = (UsbManager) getSystemService(Context.USB_SERVICE);

        deviceUpdateReceiver = new DeviceUpdateReceiver();
        IntentFilter filter1 = new IntentFilter();
        filter1.addAction("deviceUpdate");
        registerReceiver(deviceUpdateReceiver, filter);

        dprotocl.setDprotocolCall(new DProtocol.DprotocolCall() {
            @Override
            public void disconnected() {
                if (usbServiceCall1 != null) {
                    usbServiceCall1.disconnect();//通知附件获取失败
                }
            }

            @Override
            public void channel(int channel) {
                if (usbServiceCall2 != null) {
                    usbServiceCall2.onChannel(channel);//发送接收到的信道
                }
            }

            @Override
            public void uavInfo(ViewPagerItem uav_o) {
                long ret = SqliteDeviceOperate.getInstance(USBConnetService.this).Insert(uav_o);
                VersionBean bean = new VersionBean();
                BaseFinal.CurrentDeviceName = uav_o.getName();
                bean.setDeviceVersion(uav_o.getMsg());
                bean.setName(uav_o.getName());
                long ret1 = SqliteVersionOperate.getInstance(USBConnetService.this).Insert(bean);
                if (ret > 0) {
                    usbServiceCall1.onVersion(true);
                } else {
                    usbServiceCall1.onVersion(false);
                }
            }

            @Override
            public void battery(int battery) {
                if (usbServiceCall2 != null) {
                    usbServiceCall2.onBattery(battery);//反馈设备电量信息
                }
            }

            @Override
            public void deviceUpdate(int position) {
                isenable = NotificationManagerCompat.from(USBConnetService.this).areNotificationsEnabled();
                if (isenable) {
                    if (position == 1) {
                        builder = new NotificationCompat.Builder(USBConnetService.this.getApplicationContext());
                        manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                        builder.setSmallIcon(R.mipmap.ic_launcher);
                        builder.setContentTitle(getResources().getString(R.string.device_loading));
                        builder.setProgress(100, 0, true);
                        builder.setOngoing(true);
                        manager.notify(5, builder.build());
                    } else if (position == 2) {
                        builder.setContentTitle(getResources().getString(R.string.device_install));
                        builder.setProgress(100, 0, true);
                        builder.setOngoing(true);
                        manager.notify(5, builder.build());
                    } else if (position == 3) {
                        builder.setContentTitle(getResources().getString(R.string.device_restart));
                        builder.setProgress(100, 0, true);
                        builder.setOngoing(true);
                        manager.notify(5, builder.build());
                    } else if (position == 4) {
                        builder.setContentTitle(getResources().getString(R.string.device_activate));
                        builder.setProgress(100, 0, true);
                        builder.setOngoing(true);
                        manager.notify(5, builder.build());
                        manager.cancel(5);
                    } else {
                        manager.cancel(5);
                    }
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
                        Intent intent = new Intent("deviceUpdate");
                        intent.putExtra("position", position);
                        sendBroadcast(intent);
                    }
                } else {
                    Intent intent = new Intent("deviceUpdate");
                    intent.putExtra("position", position);
                    sendBroadcast(intent);
                }
            }

            @Override
            public void videoResolution(int width, int height, int fps) {

            }
        });
        connectToAccessory();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return new UsbBinder();
    }

    public class UsbBinder extends Binder {
        public USBConnetService getService() {
            return USBConnetService.this;
        }
    }

    public void AccessoryAttached() {
        if (threadExecutor == null) {
            threadExecutor = Executors.newFixedThreadPool(1);
        }
        if (usbDataRunnable == null) {
            usbDataRunnable = new SendUsbDataRunnable();
        }
        savaInfoToSD("send order Attached 发送连接指令");
        usbDataRunnable.usbData = new byte[255];
        usbDataRunnable.doffset = 0;
        usbDataRunnable.usbDataLength = DFrame.genDFrameAccessoryAttached(usbDataRunnable.usbData, usbDataRunnable.usbData.length);
        threadExecutor.execute(usbDataRunnable);
    }

    public void startReceive() {
        if (threadExecutor == null) {
            threadExecutor = Executors.newFixedThreadPool(1);
        }
        if (usbDataRunnable == null) {
            usbDataRunnable = new SendUsbDataRunnable();
        }
        savaInfoToSD("send order start 发送开始指令");
        usbDataRunnable.usbData = new byte[255];
        usbDataRunnable.doffset = 0;
        usbDataRunnable.usbDataLength = DFrame.genDFrameStartVideoTrans(usbDataRunnable.usbData, usbDataRunnable.usbData.length);
        codecData = new CodecData();
        codecData.start();
        threadExecutor.execute(usbDataRunnable);
        ServiceStatic.isStartUsbPreview = true;
    }

    public void stopReceive() {
        //直接退出时中断录像
        if (ServiceStatic.isVideoStart && !ServiceStatic.videoisEnd) {
            savaInfoToSD("video Exception stop---------停止录像-----");
            saveEnd();
            stopRecord();
        }
        if (threadExecutor == null) {
            threadExecutor = Executors.newFixedThreadPool(1);
        }
        if (usbDataRunnable == null) {
            usbDataRunnable = new SendUsbDataRunnable();
        }
        savaInfoToSD("send order stop 发送停止指令");
        usbDataRunnable.usbData = new byte[255];
        usbDataRunnable.doffset = 0;
        usbDataRunnable.usbDataLength = DFrame.genDFrameStopVideoTrans(usbDataRunnable.usbData, usbDataRunnable.usbData.length);
        threadExecutor.execute(usbDataRunnable);
        if (codecData != null) {
            codecData.setStop(true);
        }
        ServiceStatic.isStartUsbPreview = false;
    }

    //发送指令
    public void SendToUsb(byte[] bys, int offset, int len) {
        if (threadExecutor == null) {
            threadExecutor = Executors.newFixedThreadPool(1);
        }
        if (usbDataRunnable == null) {
            usbDataRunnable = new SendUsbDataRunnable();
        }
        usbDataRunnable.usbData = bys;
        usbDataRunnable.doffset = offset;
        usbDataRunnable.usbDataLength = len;
        threadExecutor.execute(usbDataRunnable);
    }

    int unTime;
    boolean isSendSearch;
    private SaveMp4 saveMp4;

    class CodecData extends Thread {
        private boolean isStop;

        public void setStop(boolean isStop) {
            this.isStop = isStop;
        }

        @Override
        public void run() {
            while (!isStop) {
                if (vector.size() > 0) {
                    CodecBean codecBean = vector.remove(0);
                    byte[] buf = codecBean.getData();
                    int len = codecBean.getLength();
                    int leng = -1;
                    int est_frame_len;
                    int ret = 0;
                    RtpPkt rtpPkt = new RtpPkt(buf, 8, len - 8);
                    ret = pktBuffer.addPkt(rtpPkt);//ret检测用
                    FrameNode frame = pktBuffer.popOldestFrame();
                    if (frame == null) {
                        continue;
                    }
                    est_frame_len = frame.getFrameEstLen();
                    byte[] frame_bytes = new byte[est_frame_len];
                    leng = frame.getData(frame_bytes, 0, frame_bytes.length);

                    if (usbServiceCall2 != null) {
                        usbServiceCall2.onUndecodeframeget(frame_bytes, 0, leng);
                        byte[] save = new byte[leng];
                        System.arraycopy(frame_bytes, 0, save, 0, leng);
                        if(isRecord){
                            int type = save[4] & 0x1f;
                            if(x==0){
                                if(type==7){
                                    bufferVector.add(ByteBuffer.wrap(save));
                                    x++;
                                }
                            }else{
                                bufferVector.add(ByteBuffer.wrap(save));
                                x++;
                                if(x%ServiceStatic.recordFps==0){
                                    //计时标志
                                    usbServiceCall2.onRecordTime(x);
                                }
                            }

                        }
                        /*if (BaseStatic.videoisLaunch) {
                            if (saveMp4 == null) {
                                saveMp4 = new SaveMp4();
                                threadExecutor.execute(saveMp4);
                            } else {
                                if (!saveMp4.isAlive) {
                                    threadExecutor.execute(saveMp4);
                                }
                            }
                            saveMp4.addData(save, leng);
                        }*/
                    } else {
                        savaInfoToSD("callback = null 预览接收界面关闭");
                        //外部接收异常，跳出循环，避免堵塞
                        continue;
                    }
                } else {
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    if (!isSendSearch) {
                        unTime++;
                    }
                    if (unTime > 50) {
                        isSendSearch = true;
                        unTime = 0;
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                isSendSearch = false;
                            }
                        }, 5000);
                    }
                }
            }
        }
    }
    private Vector<ByteBuffer> bufferVector;
    private RecordMp4 recordMp4;
    private boolean isRecord;//是否开始录像
    public void startRecord() {
        if (bufferVector == null) {
            bufferVector = new Vector<>();
        }
        bufferVector.clear();
        if(recordMp4==null){
            recordMp4 = new RecordMp4();
        }
        if(!recordMp4.isStart()){
            recordMp4.start();
            new Thread(recordMp4).start();
            isRecord = true;
        }
    }

    public void stopRecord() {
        if(recordMp4!=null){
            recordMp4.stop();
            isRecord = false;
        }
    }

    public void updataDevice() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                dprotocl.dprotocol_check_upgrade();
            }
        }).start();
    }

    //连接附件
    private void connectToAccessory() {
        if (mFileDescriptor != null) {
            savaInfoToSD("UsbService connectToAccessory mFileDescriptor ! = null");
            return;
        }
        if (ServiceStatic.isAcceptData) {
            savaInfoToSD("UsbService connectToAccessory isAcceptData true");
            return;
        }
        UsbAccessory[] accessories = mUSBManager.getAccessoryList();
        mAccessory = (accessories == null ? null : accessories[0]);
        savaInfoToSD("UsbService mAccessory = " + mAccessory);

    }

    public void startAccessory() {
        if (mAccessory != null) {
            if (mUSBManager.hasPermission(mAccessory)) {
                savaInfoToSD("UsbService isAccessoryConnect is true");
                ServiceStatic.isAccessoryConnect = true;
                openAccessory(mAccessory);
            } else {
                PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
                mUSBManager.requestPermission(mAccessory, pendingIntent);
                savaInfoToSD("UsbService accessory请求权限");
            }
        } else {
            ServiceStatic.isAccessoryConnect = false;//mAccessory = null
            savaInfoToSD("UsbService connectToAccessory mAccessory = null");
            if (usbServiceCall1 != null) {
                usbServiceCall1.disconnect();//通知附件获取失败
                stopSelf();
            }
        }
    }

    //打开附件--同时识别附件
    private void openAccessory(UsbAccessory accessory) {
        if (mFileDescriptor != null) {
            savaInfoToSD("openAccessory mFileDescriptor != null");
            return;
        }
        if (ServiceStatic.isAcceptData) {
            savaInfoToSD("UsbService openAccessory isAcceptData true");
            return;
        }
        mFileDescriptor = mUSBManager.openAccessory(accessory);
        if (mFileDescriptor != null) {
            savaInfoToSD("openAccessory success");
            fd = mFileDescriptor.getFileDescriptor();
            mInputStream = new FileInputStream(fd);
            mOutputStream = new FileOutputStream(fd);
            if (mInputStream == null || mOutputStream == null) {
                savaInfoToSD("openAccessory mInputStream or mOutputStream is null");
                mInputStream = null;
                mOutputStream = null;
                mFileDescriptor = null;
                return;
            }
            //文件链接成功后发送启动指令
            AccessoryAttached();
            ServiceStatic.isAcceptData = true;
            setDataThread = new Thread(setFpvDataRunnable);
            setDataThread.start();
            if (usbServiceCall1 != null) {
                usbServiceCall1.connect();//通知已获取到附件
            }
        } else {
            savaInfoToSD("openAccessory mFileDescriptor is null");
        }
    }

    //关闭附件
    public void closeAccessory() {
        savaInfoToSD("closeAccessory");
        try {
            if (mInputStream != null) {
                mInputStream.close();
            }
        } catch (IOException e) {
            BaseStatic.savaInfoToSD("close===mInputStream====" + e.getLocalizedMessage() + e.getMessage());
        }
        try {
            if (mOutputStream != null) {
                mOutputStream.close();
            }
        } catch (IOException e) {
            BaseStatic.savaInfoToSD("close===mOutputStream====" + e.getLocalizedMessage() + e.getMessage());
        }
        try {
            if (mFileDescriptor != null) {
                mFileDescriptor.close();
            }
        } catch (IOException e) {
            BaseStatic.savaInfoToSD("close===mFileDescriptor====" + e.getLocalizedMessage() + e.getMessage());
        }
        mOutputStream = null;
        mInputStream = null;
        mFileDescriptor = null;
        mAccessory = null;
        BaseStatic.savaInfoToSD("close is finally");
    }

    private int input_null, read_null;
    private int acceptTime = 0;

    private class FpvDataRun implements Runnable {
        @Override
        public void run() {

            input_null = 0;
            read_null = 0;
            while (ServiceStatic.isAcceptData) {

                int len = -1;
                byte[] buf = null;
                while (ServiceStatic.isAcceptData) {

                    try {
                        if (mInputStream != null) {
                            if (buf == null) {
                                buf = new byte[16 * 1024];
                            }
                            if (timer == null) {
                                timer = new Timer();
                            }
                            time = System.currentTimeMillis();
                            //myTask只能执行一次，因此每次都必须移除然后新建
                            if (myTask != null) {
                                myTask.cancel();
                            }
                            myTask = new MyTask();
                            timer.schedule(myTask, 5000);
                            len = mInputStream.read(buf);//此处会阻塞--长时间阻塞代表连接异常---因为每秒钟会收到电量信息
                            if (timer != null) {
                                timer.cancel();
                                timer.purge();
                                timer = null;
                                time = System.currentTimeMillis();
                            }

                            if (len > 0) {
                                DFrame dframe = new DFrame(buf, len);
                                switch (dframe.getType()) {
                                    case DFrameType.DFRAME_TYPE_RTP: // 2
                                        CodecBean codecBean = new CodecBean(buf, len);
                                        vector.add(codecBean);
                                        break;

                                    case DFrameType.DFRAME_TYPE_DPROTOCOL: //10
                                        dprotocl.dprotocol_input(buf, BaseStatic.HeaderLen, len - BaseStatic.HeaderLen);
                                        break;

                                    case DFrameType.DFRAME_TYPE_NONE: // 0
                                        savaInfoToSD("dismiss this package len = " + len);
                                        break;
                                }

                            } else {
                                savaInfoToSD("UsbService read len <= 0 is " + len);
                            }
                            read_null = 0;
                            input_null = 0;
                            buf = null;
                        } else {
                            //当mInputStream为空时跳出循环，避免堵塞
                            input_null++;
                            if (input_null > 2) {
                                if (BaseStatic.videoisLaunch) {
                                    saveEnd();//连接断开
                                    stopRecord();
                                }
                                savaInfoToSD("input_null == " + input_null + " 开启文件表述符获取InputStream为空");
                                ServiceStatic.isAcceptData = false;
                                ServiceStatic.isAccessoryConnect = false;
                                if (usbServiceCall1 != null) {
                                    usbServiceCall1.disconnect();//通知附件获取失败
                                    stopSelf();
                                }
                            }
                            break;
                        }
                    } catch (Exception e1) {
                        //当读取数据异常时跳出循环(多数时候为断开usb连接)，避免堵塞
                        savaInfoToSD("read_null = " + read_null + e1.getMessage());
                        read_null++;
                        if (read_null > 2) {
                            if (BaseStatic.videoisLaunch) {
                                saveEnd();//异常关闭
                                stopRecord();
                            }
                            savaInfoToSD("read_null == " + read_null + " 读取数据异常捕获，通常为usb连接断开后发生");
                            ServiceStatic.isAcceptData = false;
                            ServiceStatic.isAccessoryConnect = false;
                            if (usbServiceCall1 != null) {
                                usbServiceCall1.disconnect();//通知附件获取失败
                                stopSelf();
                            }
                        }
                        break;
                    }
                }

            }
        }
    }

    private FpvDataRun setFpvDataRunnable = new FpvDataRun();

    MediaMuxer mediaMuxer = null;
    int save_x = 0;//分割数据提取sps,pps
    byte[] sps, pps;
    int trackIndex;//mediamuxer写入标志位
    int x = 0;//创建mediaMuxer实例标志
    Map<Integer, Integer> map;//保存分割位置
    FileOutputStream fos;
    String pic_path;
    int video_time;
    String mp4_path;
    long startTime, endTime;
    //使用系统空间MediaMuxer生成MP4--存在电脑上不能播放的问题，不是标准文件
    class SaveMp4 implements Runnable {
        private Vector<CodecBean> vectorCodec;
        public boolean isAlive;

        public SaveMp4() {
            vectorCodec = new Vector<>();
        }

        public void addData(byte[] save, int len) {
            CodecBean bean = new CodecBean(save, len);
            vectorCodec.add(bean);
        }

        @Override
        public void run() {
            while (!ServiceStatic.videoisEnd && BaseStatic.videoisLaunch) {
                isAlive = true;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                    if (vectorCodec.size() == 0) {
                        try {
                            Thread.sleep(1000);
                            continue;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    CodecBean bean = vectorCodec.remove(0);
                    if (mediaMuxer == null) {
                        try {
                            BaseStatic.savaInfoToSD("mediaMuxer is create");
                            File dirFile = new File(BaseStatic.MediaPath);
                            if (!dirFile.exists()) {
                                dirFile.mkdirs();
                            }
                            mp4_path = BaseStatic.MediaPath + "/" + paserTime(System.currentTimeMillis()) + ".mp4";
                            mediaMuxer = new MediaMuxer(mp4_path, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
                        } catch (IOException e) {
                            e.printStackTrace();
                            BaseStatic.savaInfoToSD("mediaMuxer is create IOException = " + e.getMessage());
                        }
                    }
                    byte[] save = bean.getData();
                    int len = bean.getLength();
                    int type = save[4] & 0x1f;
                    ByteBuffer byteBuffer;
                    if (type == 7 && x == 0) {
                        map = new HashMap<>();
                        for (int j = 0; j < len - 3; j++) {
                            if (save[j] == 0 && save[j + 1] == 0 && save[j + 2] == 0 && save[j + 3] == 1) {
                                map.put(save_x, j);
                                save_x++;
                            }
                        }
                        save_x = 0;
                        int length_sps = map.get(1) - map.get(0) - 4;
                        int offset_sps = map.get(0) + 4;
                        sps = new byte[length_sps];
                        System.arraycopy(save, offset_sps, sps, 0, length_sps);
                        int length_pps = map.get(2) - map.get(1) - 4;
                        int offset_pps = map.get(1) + 4;
                        pps = new byte[length_pps];
                        System.arraycopy(save, offset_pps, pps, 0, length_pps);
                        if (ServiceStatic.recordWidth == 0 || ServiceStatic.recordHeight == 0) {
                            ServiceStatic.recordWidth = 720;
                            ServiceStatic.recordHeight = 480;
                        }
                        MediaFormat videoformat = MediaFormat.createVideoFormat("video/avc", ServiceStatic.recordWidth, ServiceStatic.recordHeight);
                        videoformat.setByteBuffer("csd-0", ByteBuffer.wrap(sps));
                        videoformat.setByteBuffer("csd-1", ByteBuffer.wrap(pps));
                        videoformat.setInteger(MediaFormat.KEY_COLOR_FORMAT, 0x7F420888);
                        videoformat.setInteger(MediaFormat.KEY_MAX_INPUT_SIZE, ServiceStatic.recordWidth * ServiceStatic.recordHeight);
                        if (ServiceStatic.recordFps == 0) {
                            ServiceStatic.recordFps = 25;
                        }
                        videoformat.setInteger("capture-rate", ServiceStatic.recordFps);
                        trackIndex = mediaMuxer.addTrack(videoformat);
                        mediaMuxer.start();
                        x++;
                        ServiceStatic.isVideoStart = true;
                        startTime = System.currentTimeMillis();
                    }
                    if (type == 7 && x == 1) {
                        byteBuffer = ByteBuffer.allocate(len);
                        byteBuffer.put(save, 0, len);
                        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                        bufferInfo.offset = 0;
                        bufferInfo.size = len;
                        bufferInfo.flags = 1;
                        bufferInfo.presentationTimeUs = 1000000l * (video_time + 1l) / ServiceStatic.recordFps;
                        try {
                            mediaMuxer.writeSampleData(trackIndex, byteBuffer, bufferInfo);
                        } catch (Exception e) {
                            BaseStatic.savaInfoToSD("mediaMuxer Exception = " + video_time + "=====\n" + e.getLocalizedMessage());
                        }
                        video_time++;
                    } else if (type != 7 && x == 1) {
                        byteBuffer = ByteBuffer.allocate(len);
                        byteBuffer.put(save, 0, len);
                        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                        bufferInfo.offset = 0;
                        bufferInfo.size = len;
                        bufferInfo.flags = 0;
                        /*if (ServiceStatic.videoisEnd && ServiceStatic.isVideoStart){
                            bufferInfo.flags = MediaCodec.BUFFER_FLAG_END_OF_STREAM;
                        }*/
                        bufferInfo.presentationTimeUs = 1000000l * (video_time + 1l) / ServiceStatic.recordFps;

                        try {
                            mediaMuxer.writeSampleData(trackIndex, byteBuffer, bufferInfo);
                        } catch (Exception e) {
                            BaseStatic.savaInfoToSD("mediaMuxer Exception = " + video_time + "=====\n" + e.getLocalizedMessage());
                        }
                        video_time++;
                    }
                    if (video_time % 30 == 0) {
                        usbServiceCall2.onRecordTime(video_time);
                    }
                }
            }
            if (ServiceStatic.videoisEnd && ServiceStatic.isVideoStart) {
                BaseStatic.savaInfoToSD("mediaMuxer normal stop---------------------------------");
                saveEnd();
                isAlive = false;
            }
        }
    }

    //使用JCodec生成MP4--都可以播放，注意timescale理解为采样率，duration为采样率除以fps,pts为帧数乘以duration。
    private int frameNo,entryNo;
    class RecordMp4 implements Runnable {
        private MuxerTrack track;
        private MP4Muxer muxer;
        private SeekableByteChannel file;
        private boolean isStart, isEnd;

        public void stop() {
            isEnd = true;
        }

        //runnable没有销毁时使用该方法设定isStart,然后执行Runnable
        public void start() {
            isStart = true;
        }

        public boolean isStart(){
            return isStart;
        }

        @Override
        public void run() {
            try {
                File dirFile = new File(BaseStatic.MediaPath);
                if (!dirFile.exists()) {
                    dirFile.mkdirs();
                }
                mp4_path = BaseStatic.MediaPath + "/" + paserTime(System.currentTimeMillis()) + ".mp4";
                File outFile = new File(mp4_path);
                file = NIOUtils.writableChannel(outFile);
                muxer = MP4Muxer.createMP4MuxerToChannel(file);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            isStart = true;
            while (isStart) {
                if (bufferVector==null||bufferVector.size() == 0) {
                    if (isEnd) {
                        bufferVector.clear();
                        BaseStatic.savaInfoToSD("entryNo = "+entryNo);
                        try {
                            muxer.finish();
                            file.close();
                            track = null;
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        isEnd = false;
                        isStart = false;
                        saveMp4ToSDCard();
                        break;
                    }
                    try {
                        Thread.sleep(200);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    continue;
                }
                ByteBuffer byteBuffer = bufferVector.remove(0);
                entryNo++;
                int type = byteBuffer.get(5)&0x1f;
                MP4Packet packet = null;

                if(type==7){
                    packet = MP4Packet.createMP4Packet(byteBuffer,entryNo*600/ServiceStatic.recordFps,600,600/ServiceStatic.recordFps,entryNo, Packet.FrameType.KEY,TapeTimecode.tapeTimecode(entryNo,false,ServiceStatic.recordFps),0,entryNo*600/ServiceStatic.recordFps,entryNo);
                }else{
                    packet = MP4Packet.createMP4Packet(byteBuffer,entryNo*600/ServiceStatic.recordFps,600,600/ServiceStatic.recordFps,entryNo, Packet.FrameType.INTER,TapeTimecode.tapeTimecode(entryNo,false,ServiceStatic.recordFps),0,entryNo*600/ServiceStatic.recordFps,entryNo);
                }

                //Packet packet = bhf.getPacket(byteBuffer);
                if(packet==null){
                    BaseStatic.savaInfoToSD("packet = null");
                    continue;
                }

                if (track == null) {
                    track = muxer.addVideoTrack(Codec.H264, new H264Decoder().getCodecMeta(packet.getData()));
                    BaseStatic.savaInfoToSD("track is create");
                }
                try {
                    track.addFrame(packet);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void saveEnd() {
        if (mediaMuxer != null) {
            mediaMuxer.stop();
            mediaMuxer.release();
            mediaMuxer = null;
        }
        saveMp4ToSDCard();
    }

    //录制完成文件及属性写入数据库
    private void saveMp4ToSDCard(){
        endTime = System.currentTimeMillis();
        //String videoTime = MyMethod.getDateTimeByMillisecond(endTime - startTime, "mm:ss");
        if (ServiceStatic.recordFps == 0) {
            ServiceStatic.recordFps = 25;
        }
        String videoTime = MyMethod.getDateTimeByMillisecond(video_time * 1000l / ServiceStatic.recordFps, "mm:ss");
        String time = MyMethod.getDateTimeByMillisecond(entryNo * 1000l / ServiceStatic.recordFps, "mm:ss");
        BaseStatic.videoisLaunch = false;
        video_time = 0;
        x = 0;//录制完成，开始标志清0
        entryNo = 0;
        ServiceStatic.isVideoStart = false;
        File file = new File(mp4_path);
        if (file.exists() && file.length() != 0) {
            // TODO: 录制完成，存入数据库
            int isLocal = 10;
            if (BaseFinal.CurrentDeviceName.equals("IWT-AGS58")) {
                isLocal = 2;
            }
            FileBean bean = new FileBean(null, file.getName(), time, file.getPath(), null, file.length(), endTime, 0, isLocal, 0);
            SqliteMediaOperation.getInstence(this).Insert(bean);
        }
        if (!ServiceStatic.isAccessoryConnect) {
            stopSelf();
        }
    }

    private static String paserTime(long milliseconds) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        return format.format(new Date(milliseconds));
    }

    //关闭服务
    @Override
    public void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mUsbReceiver);
        unregisterReceiver(deviceUpdateReceiver);
        stopReceive();
        if (mAccessory != null) {
            closeAccessory();
        }
        ServiceStatic.isLaunchUsbService = false;
        if (timer != null) {
            timer.cancel();
            timer.purge();
            timer = null;
            savaInfoToSD("onDestroy timer = null");
        }
        if (myTask != null) {
            myTask.cancel();
            myTask = null;
        }
        savaInfoToSD("UsbService Destroy");
        BaseStatic.RecordToSD();
    }
}
